<?php

require_once 'lib.php';

/**
 * class PDOGuestbook
 * 
 * PDO implementation
 * 
 * @author Kirill Krasnoschekov
 */
class PDOGuestbook extends Guestbook 
{
    // PDO Database handler
    private $DBH;
    
    // Table names  
    private $msgTable = "gb_message";
    private $commentTable = "gb_comment";



    /**
     * Constructor
     * 
     * Connect to DB, set error handling to exceptions 
     * and some other attributes.
     */
    public function __construct    
    ($server, $username, $password, $dbname)
    {
        // Connect and select DB
        try
        {
            $this->DBH = new PDO
                ("mysql:host={$server};dbname={$dbname}", $username, $password);
        } 
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
        
        // Set exceptions error handling style
        $this->DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        
        // Set default fetch mode to dictionaries
        $this->DBH->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    }
    
    /**
     * Destructor
     */
    public function __destruct()
    {
        $this->DBH = NULL;
    }
    
    
    
    /**
     * CountPages
     * 
     * @return integer Amount of pages (starting with 0)
     */
    public function CountPages()
    {
        try
        {
            $STH = $this->DBH->query
                ("SELECT COUNT(*) as count FROM {$this->msgTable}");
            $rec = $STH->fetch();

            return ceil($rec['count'] / $this->messagesPerPage);
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }

    /**
     * FetchMessages
     * 
     * Fetch messages from the given page
     * 
     * @param $page Page number
     */
    public function FetchMessages($page)
    {
        // Calculating message numbers on the given page
        $numStart = $page * $this->messagesPerPage;
        $numEnd = $numStart + $this->messagesPerPage;

        // Selecting messages from the given page
        try
        {
            // Prepare
            $STH = $this->DBH->prepare
                ("SELECT id, name, text, timestamp 
                FROM {$this->msgTable} 
                ORDER BY timestamp DESC
                LIMIT :numStart, :numEnd");
            $STH->bindParam('numStart', $numStart, PDO::PARAM_INT);
            $STH->bindParam('numEnd', $numEnd, PDO::PARAM_INT);
                
            // Execute
            $STH->execute();
            
            // Return
            return $STH->fetchAll();
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    /**
     * FetchComments
     * 
     * Fetch comments for the given message
     * 
     * @param $msgid Message ID
     */
    public function FetchComments($msgid)
    {
        // Selecting comments from the given page
        try
        {
            // Prepare
            $STH = $this->DBH->prepare
                ("SELECT id, name, text, timestamp 
                FROM {$this->commentTable}
                WHERE msgid=:id 
                ORDER BY timestamp");
            $STH->bindParam('id', $msgid, PDO::PARAM_INT);
                
            // Execute
            $STH->execute();

            // Return
            return $STH->fetchAll();
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    

    
    /**
     * AddMessage
     * 
     * Add a message to the guestbook
     * 
     * @param $name User name
     * @param $text Message text 
     */
    public function AddMessage($name, $text)
    {
        try
        {
            // Prepare
            $STH = $this->DBH->prepare
                ("INSERT INTO {$this->msgTable} (name, text)
                VALUES (:name, :text)");
                
            // Execute
            $STH->execute(array('name' => $name, 'text' => $text));
            
            return True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    /**
     * AddComment
     * 
     * Add a comment to the given message
     * 
     * @param integer $msgid Message id
     * @param string $name User name
     * @param string $text Comment text
     */
    public function AddComment($msgid, $name, $text)
    {
        // Checking if message does not exist
        $this->MessageExists($msgid) or die(self::$err['MSGID_NOT_FOUND']);
        
        // Adding the comment
        try
        {
            // Prepare
            $STH = $this->DBH->prepare
                ("INSERT INTO {$this->commentTable} (msgid, name, text)
                VALUES (:msgid, :name, :text)");
            $STH->bindParam('msgid', $msgid, PDO::PARAM_INT);
            $STH->bindParam('name', $name, PDO::PARAM_STR);
            $STH->bindParam('text', $text, PDO::PARAM_STR);
            
            // Execute
            $STH->execute();
            
            return True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }


    
    /**
     * DeleteMessage
     * 
     * Delete the message from the guestbook
     * 
     * @param int $msg_id ID of the message to delete
     */
    public function DeleteMessage($msgid)
    {
        // Checking if message does not exist
        $this->MessageExists($msgid) or die(self::$err['MSGID_NOT_FOUND']);
        
        try
        {
            // Deleting all the comments to this message
            $STH = $this->DBH->prepare
                ("DELETE FROM {$this->commentTable} WHERE msgid=:msgid");
            $STH->bindParam('msgid', $msgid, PDO::PARAM_INT);
            $STH->execute();
            
            // Deleting the message
            $STH = $this->DBH->prepare
                ("DELETE FROM {$this->msgTable} WHERE id=:msgid");
            $STH->bindParam('msgid', $msgid, PDO::PARAM_INT);
            $STH->execute();
                        
            return True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    /**
     * DeleteComment
     * 
     * Delete the comment from the guestbook
     * 
     * @param int $commentid ID of the comment to delete
     */
    public function DeleteComment($commentid)
    {
        // Checking if message does not exist
        $this->CommentExists($commentid) or die(self::$err['COMMENTID_NOT_FOUND']);
        
        try
        {
            // Deleting the comment
            $STH = $this->DBH->prepare
                ("DELETE FROM {$this->commentTable} WHERE id=:commentid");
            $STH->bindParam('commentid', $commentid, PDO::PARAM_INT);
            $STH->execute();

            return True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    
    
    /**
     * UpdateMessage
     * 
     * Update selected message
     * 
     * @param int $msgid Message ID
     * @param string $name New user name
     * @param string $text New message text
     */
    public function UpdateMessage($msgid, $name, $text)
    {
        // Checking if message does not exist
        $this->MessageExists($msgid) or die(self::$err['MSGID_NOT_FOUND']);

        try
        {
            // Prepare
            $STH = $this->DBH->prepare
                ("UPDATE {$this->msgTable}
                SET name=:name, text=:text
                WHERE id=:msgid");
            $STH->bindParam('msgid', $msgid, PDO::PARAM_INT);
            $STH->bindParam('name', $name, PDO::PARAM_STR);
            $STH->bindParam('text', $text, PDO::PARAM_STR);
                
            // Execute
            $STH->execute();
            
            return True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    
    /**
     * MessageExists
     * 
     * @param int $msgid Message ID
     * @return True if yes, False if no
     */    
    protected function MessageExists($msgid)
    {
        try
        {
            // Preparing the statement
            $STH = $this->DBH->prepare
                ("SELECT * FROM {$this->msgTable} WHERE id=:id");
            $STH->bindParam('id', $msgid, PDO::PARAM_INT);
                
            // Executing the statement
            $STH->execute();
            
            // Checking the result
            return ($STH->rowCount() != 1) ? False : True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }
    }
    
    /**
     * CommentExists
     * 
     * @param int $commentid Comment ID
     * @return True if yes, False if no
     */    
    protected function CommentExists($commentid)
    {
        try
        {
            // Preparing the statement
            $STH = $this->DBH->prepare
                ("SELECT * FROM {$this->commentTable} WHERE id=:id");
            $STH->bindParam('id', $commentid, PDO::PARAM_INT);
                
            // Executing the statement
            $STH->execute();
            
            // Checking the result
            return ($STH->rowCount() != 1) ? False : True;
        }
        catch (PDOException $e)
        {
            $this->HandleException($e);
        }        
    }       
    
    
    
    /**
     * HandleException
     * 
     * Handle the database exception and exit
     * 
     * @param PDOException $e
     */
    private function HandleException(PDOException $e)
    {
        $file = $e->getFile();
        $line = $e->getLine();
        $message = $e->getMessage();
        
        // Just die
        print "<p><b>Error</b> in <b>{$file}</b> at <b>line {$line}</b>: <br> {$message}</p>";
        die ();
    }     
}

?>